#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define MSG_SIZE 80
#define MAX_CLIENTS 95
#define MYPORT 7400



/**
* This method will be used to clear client's data.
* @author Tadeusz Wieja 
* @param fd  This is filedescriptorow.
* @param *readfds This is set file descriptorow.
* @param fd_array[] This is array file descryptorow.
* @return Polaczenie zakonczone
* @date 04/20/2012
*/
void exitClient(int fd, fd_set *readfds, char fd_array[], int *num_clients) {
	int i;

	close(fd);
	FD_CLR(fd, readfds);

	/// czyszczenie danych klienta, ktory sie rozlacza
	for (i = 0; i < (*num_clients) - 1; i++)
		if (fd_array[i] == fd)
			break;
	for (; i < (*num_clients) - 1; i++)
		(fd_array[i]) = (fd_array[i + 1]);
	(*num_clients)--;
}
/*! 
* This method will be used to clear client's data.
* @author Kamil smuga
* @param argc 
* @param *argv[] 
* @return Polaczenie
* @date 04/20/2012
*/
int main(int argc, char *argv[]) {
	int i = 0;

	int port;
	int num_clients = 0;
	struct sockaddr_in server_address;
	int addresslen = sizeof(struct sockaddr_in);
	int fd;
	char fd_array[MAX_CLIENTS];
	fd_set readfds, testfds, clientfds;
	char msg[MSG_SIZE + 1];
	char kb_msg[MSG_SIZE + 10];

	/// Zmienne klienta
	int sockfd;
	int result;
	char hostname[MSG_SIZE];
	struct hostent *hostinfo;
	struct sockaddr_in address;
	char alias[MSG_SIZE] = "alias: ";
	int clientid;

	/// Klient
	if (argc == 2 || argc == 4) {
		if (!strcmp("-p", argv[1])) {
			if (argc == 2) {
				printf("Zle parametry.\nUzycie: client [-p PORT] adresIP\n");
				exit(0);
			} else {
				sscanf(argv[2], "%i", &port);
				strcpy(hostname, argv[3]);
			}
		} else {
			port = MYPORT;
			strcpy(hostname, argv[1]);
		}
		printf("\n*** Start klienta... (wpisz \"quit\" zeby zatrzymac): \n");
		fflush(stdout);

		/// Tworzenie socketa dla klienta 
		sockfd = socket(AF_INET, SOCK_STREAM, 0);

		/// Wypelnienie struktury sockaddr_in 
		hostinfo = gethostbyname(hostname); 
		address.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list;
		address.sin_family = AF_INET;
		address.sin_port = htons(port);

		/// Polaczenie socketu z socketem serwera 
		if (connect(sockfd, (struct sockaddr *) &address, sizeof(address))
				< 0) {
			perror("laczenie...");
			exit(1);
		}

		fflush(stdout);

		FD_ZERO(&clientfds);
		FD_SET(sockfd, &clientfds);
		FD_SET(0, &clientfds);


		/// Petla do komunikacji z serwerem 
		while (1) {
			testfds = clientfds;
			select(FD_SETSIZE, &testfds, NULL, NULL, NULL);

			for (fd = 0; fd < FD_SETSIZE; fd++) {
				if (FD_ISSET(fd,&testfds)) {

					/*! Unconditionally shown documentation.
					*  \if fd==sockfd
					*		Akceptacja danych. Czytanie danych z otwrtego socketa
					*  \endif
					*  \if fd==0
					*    Only included if Cond2 is set.
					*    \if Cond3
					*      Aktywnosc zwiazana z czytaniem eventow klawiatury.
					*    \endif
					*    More text.
					*  \endif
					*  Unconditional text.
					*/
					if (fd == sockfd) { 
						result = read(sockfd, msg, MSG_SIZE);
						// Zakonczenie stringa nullem 
						msg[result] = '\0'; 
						printf("%s", msg + 1);

						if (msg[0] == 'X') {
							close(sockfd);
							exit(0);
						}
					} else if (fd == 0) { 

						fgets(kb_msg, MSG_SIZE + 1, stdin);
					
						if (strcmp(kb_msg, "quit\n") == 0) {
							sprintf(msg, "Klient sie zamyka...\n");
							write(sockfd, msg, strlen(msg));

							/// zamykanie klienta
							close(sockfd); 

							/// koniec programu
							exit(0); 
						} else {
							

							sprintf(msg, "M%s", kb_msg);
							write(sockfd, msg, strlen(msg));
						}
					}
				}
			}
		}
	} 

}
/*! \class Client  "sys/socket.h"
 *  \brief Klasa klienta.
 *  
 * Klasa implementujaca klienta.
 * Metody klasy:
 * exitClient(int fd, fd_set *readfds, char fd_array[], int *num_clients)
 * fd - filedescriptor 
 * readfds - This is set file descriptorow.
 * fd_array[] This is array file descryptorow.
 * *num_clients  Number of cleints.
 */
